package atomservice

import (
	"errors"
	"fmt"
	"playbook/ginsvr/src/global"
	"playbook/ginsvr/src/orm"
	"playbook/ginsvr/src/source/gene"
	"playbook/ginsvr/src/utils/uuidutil"
	"strings"

	"github.com/sirupsen/logrus"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

var db *gorm.DB
var err error

func init() {
	db, err = gorm.Open(sqlite.Open("playbook.db"), &gorm.Config{Logger: logger.Default.LogMode(logger.Info)})
}

func AddAotm(param map[string]interface{}) map[string]interface{} {
	//判断入参是否已经存在
	atomsvr, err := AddAtomParam(param)
	if err != nil {
		return map[string]interface{}{
			"respCode": "000001",
			"respMsg":  err.Error(),
		}
	}
	_, err = gene.GeneAtom(atomsvr.Atomsvrid)
	if err != nil {
		return map[string]interface{}{
			"respCode": "000001",
			"respMsg":  err.Error(),
		}
	}
	return map[string]interface{}{
		"respCode": "000000",
		"respMsg":  "新增成功",
	}
}

// 添加原子服务出入参,与原子服务
func AddAtomParam(param map[string]interface{}) (orm.AtomSvrDefine, error) {
	var atomSvrDefine orm.AtomSvrDefine
	name := param["name"].(string)
	//从atomsvrDefine查询是否存在同名原子服务
	var count int64
	db.Table("atomsvrdefine").Where("asname = ?", name).Count(&count)
	if count > 0 {
		return atomSvrDefine, errors.New("新增失败，已存在同名的原子服务")
	}
	inparamMap := []orm.Parameter{}
	outparamMap := []orm.Parameter{}
	paramRelas := []orm.Paramrelation{}
	inputParameter := param["input-parameter"].(map[string]interface{})["parameter"].(map[string]interface{})
	inputparamid := addParameter(inputParameter, &inparamMap, &paramRelas)
	outputParameter := param["output-parameter"].(map[string]interface{})["parameter"].(map[string]interface{})
	outputputparamid := addParameter(outputParameter, &outparamMap, &paramRelas)
	//存储数据库
	saveParams(inparamMap)
	saveParams(outparamMap)
	saveParamRelas(paramRelas)
	//生成出入参bean
	err = gene.GeneAtomParamBean("parambean", inputparamid)
	if err != nil {
		return atomSvrDefine, err
	}
	err = gene.GeneAtomParamBean("parambean", outputputparamid)
	if err != nil {
		return atomSvrDefine, err
	}

	//原子服务包路径
	cataagoryid := param["catagoryid"].(string)
	atomSvrDefine, err := saveAtomInfo(param, inputparamid, outputputparamid, cataagoryid)

	return atomSvrDefine, err
}

func DeleteAtom(atomServiceId string) map[string]interface{} {
	var atomService orm.AtomSvrDefine
	var count int64
	db.Table("atomsvrdefine").Where("atomsvrid = ?", atomServiceId).Find(&atomService).Count(&count)
	if count == 0 {
		return map[string]interface{}{
			"respCode": "000001",
			"respMsg":  "原子服务不存在",
		}
	}
	db.Table("activity").Where("servicebindingid = ?", atomService.Servicebindingid).Count(&count)
	if count > 0 {
		return map[string]interface{}{
			"respCode": "000001",
			"respMsg":  "原子服务已被编排，不能删除",
		}
	}
	//删除数据
	db.Exec("DELETE FROM atomsvrdefine where atomsvrid = ?", atomService.Atomsvrid)
	db.Exec("DELETE FROM service where serviceid = $1", atomService.Servicebindingid)
	return map[string]interface{}{
		"respCode": "000000",
		"respMsg":  "删除成功",
	}
}

func CopyAtom(param map[string]interface{}) map[string]interface{} {
	var atomservice orm.AtomSvrDefine
	db.Table("atomsvrdefine").Where("atomsvrid = ?", param["atomsvrid"].(string)).Find(&atomservice)
	copyAtom, err := saveAtomInfo(param, atomservice.Inputparamid, atomservice.Outputparamid, atomservice.Catagoryid)
	// var inparam orm.Parameter
	// var outparam orm.Parameter
	// db.Table("parameter").Where("parameterid = ?", atomservice.Inputparamid).Find(&inparam)
	// db.Table("parameter").Where("parameterid = ?", atomservice.Outputparamid).Find(&outparam)
	//复制文件
	if err != nil {
		return map[string]interface{}{
			"respCode": "000001",
			"respMsg":  err.Error(),
		}
	}
	gene.GeneAtom(copyAtom.Atomsvrid)
	return map[string]interface{}{
		"respCode": "000000",
		"respMsg":  "复制成功",
	}
}

// 原子服务分类列表
func ListCatagory() []orm.Catagory {
	var res = []orm.Catagory{}
	db.Table("catagorydefine").Where("cgtype = 2").Find(&res)
	return res
}

// 原子服务列表
func ListAtom(param map[string]interface{}) map[string]interface{} {
	tx := db.Table("atomsvrdefine")
	var data []orm.AtomSvrDefine
	pageNum := int(param["pageNum"].(float64))
	pageSize := int(param["pageSize"].(float64))

	if param["catagoryid"] != nil && param["catagoryid"] != "" {
		tx = tx.Where("catagoryid = ?", param["catagoryid"])
	}
	if param["name"] != nil && param["name"] != "" {
		tx = tx.Where("asname = ?", param["name"])
	}
	//查询总条数
	var count int64
	result := tx.Count(&count)
	if nil != result.Error {
		global.LOG.WithFields(logrus.Fields{
			"err": result.Error,
		}).Error("listAtom err, get total err.")
		return map[string]interface{}{
			"respCode": "000001",
			"respMsg":  result.Error.Error(),
			"data":     "",
		}
	}
	result = tx.Limit(pageSize).Offset((pageNum - 1) * pageSize).Find(&data)
	if nil != result.Error {
		global.LOG.WithFields(logrus.Fields{
			"err": result.Error,
		}).Error("listAtom err, get data err.")

		return map[string]interface{}{
			"respCode": "000001",
			"respMsg":  result.Error.Error(),
			"data":     "",
		}
	}
	caragoryList := ListCatagory()
	caragoryMap := map[string]orm.Catagory{}
	for i := 0; i < len(caragoryList); i++ {
		catagory := caragoryList[i]
		caragoryMap[catagory.Catagoryid] = catagory
	}
	for i := 0; i < len(data); i++ {
		data[i].CatagoryName = caragoryMap[data[i].Catagoryid].Catagorydesc
	}
	return map[string]interface{}{
		"respCode": "000000",
		"respMsg":  "查询成功",
		"data": map[string]interface{}{
			"data":     data,
			"total":    count,
			"pageNum":  pageNum,
			"pageSize": pageSize,
		},
	}
}

func getClasspath(catagoryid string, name string) string {
	var catagory orm.Catagory
	db.Table("catagorydefine").Where("catagoryid = ?", catagoryid).Find(&catagory)
	if catagory.Srcpath == "" {
		return ""
	}
	_, after, _ := strings.Cut(catagory.Srcpath, "com")
	return strings.ReplaceAll("com"+after+global.PTHSEP+name, global.PTHSEP, ".")
}

func saveAtomInfo(param map[string]interface{}, inputParamId string, outputParamId string, catagoryid string) (orm.AtomSvrDefine, error) {
	name := param["name"].(string)
	atomsvrid := uuidutil.GetUUID()
	serviceBindId := uuidutil.GetUUID()
	atomsvr := orm.AtomSvrDefine{
		Atomsvrid:        atomsvrid,
		Inputparamid:     inputParamId,
		Outputparamid:    outputParamId,
		Servicebindingid: serviceBindId,
		Asname:           name,
		Asdesc:           param["desc"].(string),
		Catagoryid:       catagoryid,
	}
	atomClassPath := getClasspath(catagoryid, name)
	if atomClassPath == "" {
		return atomsvr, errors.New("类路径错误")
	}
	//1.保存原子服务
	db.Table("atomsvrdefine").Create(atomsvr)
	// 2.保存service
	service := orm.Service{
		Serviceid:      serviceBindId,
		Project:        "cpcpb",
		Serviceabsname: atomClassPath,
	}
	db.Table("service").Create(service)
	atomsvr.Servicebinding = service
	return atomsvr, nil
}

func addParameter(parameter map[string]interface{}, paramMap *[]orm.Parameter, paramRelas *[]orm.Paramrelation) string {
	paramid := reflushParameterItem(parameter, paramMap)

	// //更新param时，需要先清理存量rel
	// DeleteParamRel(paramid)
	parametertype := parameter["type"]

	if parametertype == "List" {
		var subparam map[string]interface{}
		if _, ok := parameter["parameter"].(map[string]interface{}); ok {
			subparam = parameter["parameter"].(map[string]interface{})
		} else {
			subparam = parameter["parameter"].([]interface{})[0].(map[string]interface{})
		}
		//根据List中的元素类型新增；List中的元素为dto（isbasetype=1）、基本数据类型
		if _, ok := subparam["type"]; ok {
			elementype := subparam["type"]
			if elementype == "Map" {
				subparamid := addParameter(subparam, paramMap, paramRelas)
				addOrUpdateParamRel(paramid, subparamid, "lst", "1", "", paramRelas)
			} else {
				subparamid := subparam["type"]
				addOrUpdateParamRel(paramid, subparamid.(string), "lst", "0", "", paramRelas)
			}
		}
	} else if parametertype == "Map" {
		//递归新增
		if _, ok := parameter["parameter"]; ok {
			fmt.Println(parameter["parameter"])
			subparams := parameter["parameter"].([]interface{})
			for _, subParam := range subparams {
				subparamid := addParameter(subParam.(map[string]interface{}), paramMap, paramRelas)
				//新增parameter层级关系
				if (subParam.(map[string]interface{})["type"]) == "Map" {
					addOrUpdateParamRel(paramid, subparamid, "sub", "1", subParam.(map[string]interface{})["name"].(string), paramRelas)
				} else {
					addOrUpdateParamRel(paramid, subparamid, "sub", "0", "", paramRelas)
				}
			}
		}
	}
	return paramid
}

// 新增或更新参数关联信息
func addOrUpdateParamRel(parentparamid string, subparamid string, reltype string, isbasetype string, relname string, paramRelas *[]orm.Paramrelation) {
	var count int64
	db.Table("paramrelation").Where("parentparamid = ? and subparamid =?", parentparamid, subparamid).Count(&count)
	if count == 0 {
		*paramRelas = append(*paramRelas, orm.Paramrelation{
			Parentparamid: parentparamid,
			Subparamid:    subparamid,
			Reltype:       reltype,
			Isbasetype:    isbasetype,
			Relname:       relname,
		})
	}
}

func reflushParameterItem(parameter map[string]interface{}, paramMap *[]orm.Parameter) string {
	var paramid string
	name := parameter["name"]
	classpath := parameter["classPath"]
	var optional string
	if _, ok := parameter["optional"]; !ok {
		optional = ""
	} else {
		optional = parameter["optional"].(string)
	}
	parametertype := parameter["type"]
	if parametertype == "Map" && classpath != nil {
		strarr := strings.Split(classpath.(string), ".")
		name = strarr[len(strarr)-1]
	} else if parametertype == "Map" && classpath == nil {
		//当前map为编排服务的出参和入参时,暂时存空，之后再根据编排服务名称生成参数名和classpath
		name = ""
		classpath = ""
	}

	// global.LOG.Info(name.(string) + classpath.(string))
	//更新数据字典中对应的参数信息
	updDict(map[string]interface{}{
		"name":      name,
		"type":      parametertype,
		"classpath": classpath,
	})
	//在parameter表中存入参数信息
	paramid = uuidutil.GetUUID()
	*paramMap = append(*paramMap, orm.Parameter{
		Parameterid: paramid,
		Name:        name.(string),
		Type:        parametertype.(string),
		Optional:    string(optional),
		Classpath:   classpath.(string),
	})
	return paramid
}

func updDict(param map[string]interface{}) string {
	var pold map[string]interface{}
	var count int64
	db.Table("paramdefine").Where("name = ?", param["name"]).Find(&pold).Count(&count)
	delete(param, "optional")
	if count == 0 {
		param["parameterid"] = uuidutil.GetUUID()

		db.Table("paramdefine").CreateInBatches(param, 1)
		return param["parameterid"].(string)
	} else {
		db.Table("paramdefine").Where("parameterid = ?", pold["parameterid"]).Updates(param)
		return pold["parameterid"].(string)
	}
}

func saveParams(params []orm.Parameter) error {
	err := db.Table("parameter").CreateInBatches(params, 1000)
	if err.Error != nil {
		global.LOG.WithFields(logrus.Fields{
			"err": err,
		}).Error("saveParams err.")
	}
	return err.Error

}

func saveParamRelas(relas []orm.Paramrelation) error {
	err := db.Table("paramrelation").CreateInBatches(relas, 1000)
	if err.Error != nil {
		global.LOG.WithFields(logrus.Fields{
			"err": err,
		}).Error("SaveParamRelas err.")
	}
	return err.Error
}
